package top.superflow.version.db.jpa

import java.lang.reflect.Field

import javax.persistence.Column
import org.apache.commons.lang3.StringUtils
import top.superflow.exception.RequestUnsupportedException
import top.superflow.verify.Ensure
import top.superflow.version.db.{FieldPropertyVersion, FieldVersion}

class JpaFieldVersion (originalField : Any) extends FieldVersion with Ensure {
  
  notNull(originalField, "The originalField should not be nul.")
  
  originalField match {
    case field : Field => {
      val columnConfiguration = field.getAnnotation(classOf[Column])
          
      setEntityName(columnConfiguration, field)
      
      setFieldProperties(columnConfiguration, field)
    }
    
    case _ => {
      throw new RequestUnsupportedException("The originalField is not java.reflect.Field")
    }
  }
  
  def setEntityName(columnConfiguration: Column, field: Field) = {
    val configuredColumnName = columnConfiguration.name()
    val finalFieldName = if(StringUtils.isEmpty(configuredColumnName)) field.getName else configuredColumnName
    this.name.compareAndSet(this.name.get, finalFieldName)
  }
  
  def setFieldProperties(column : Any, field : Field) = {
    column match {
      case col : Column => {
        addProperties(col)
      }
      
      case _ => {
        throw new RequestUnsupportedException("The originalField is not javax.persistence.Column")
      }
    }
    
    setFieldType(field)
  }
  
  def setFieldType(field : Field) = {
    notNull(field, "The field should not be null.")
    
    this.properties += (FieldPropertyVersion.FIELD_TYPE -> new JpaFieldPropertyVersion(FieldPropertyVersion.JPA_FIELD_TYPE, field.getType.getName))
  }

  def addProperties(col: javax.persistence.Column) : Unit = {
    for(method <- col.getClass.getDeclaredMethods) {
      val methodName = method.getName
      
      if(StringUtils.equals(methodName, "name")) return
       
      val fieldPropertyVersion = new JpaFieldPropertyVersion(methodName, method.invoke(col))
      this.properties += (fieldPropertyVersion.getPublicName -> fieldPropertyVersion)
    }
  }
}